package net.danielthompson.danray.shapes;

import net.danielthompson.danray.lights.Radiatable;
import net.danielthompson.danray.shading.Material;
import net.danielthompson.danray.states.IntersectionState;
import net.danielthompson.danray.structures.BoundingBox;
import net.danielthompson.danray.structures.Point;
import net.danielthompson.danray.structures.Vector;

import java.awt.Color;

/**
 * DanRay
 * User: dthompson
 * Date: 7/12/13
 * Time: 5:23 PM
 */
public class Triangle implements Drawable, Radiatable{

   private Point _vertex0;
   private Point _vertex1;
   private Point _vertex2;

   private Point _normalDirection;

   private Material _material;

   public Triangle(Point vertex0, Point vertex1, Point vertex2, Material material) {
      _vertex0 = vertex0;
      _vertex1 = vertex1;
      _vertex2 = vertex2;

      _material = material;

      _normalDirection = _vertex1.Cross(_vertex0);
   }

   public Triangle(Point vertex0, Point vertex1, Point vertex2, Point normalDirection, Material material) {
      _vertex0 = vertex0;
      _vertex1 = vertex1;
      _vertex2 = vertex2;

      _material = material;

      _normalDirection = normalDirection;
   }

   @Override
   public Material GetMaterial() {
      return _material;
   }

   @Override
   public IntersectionState GetHitInfo(Vector vector) {
      return GetHitInfo(this, vector, _vertex0, _vertex1, _vertex2);
   }

   public static IntersectionState GetHitInfo(Drawable drawable, Vector vector, Point vertex0, Point vertex1, Point vertex2) {
      IntersectionState state = new IntersectionState();

      Point E1 = Point.Minus(vertex1, vertex0);
      Point E2 = Point.Minus(vertex2, vertex0);
      Point T = Point.Minus(vector.Origin, vertex0);
      Point Q = T.Cross(E1);
      Point P = vector.Direction.Cross(E2);

      double multiplier = 1.0 / P.Dot(E1);

      double t = Q.Dot(E2) * multiplier;
      double u = P.Dot(T) * multiplier;
      double v = Q.Dot(vector.Direction) * multiplier;

      if (t > 0 && u >= 0 && v >= 0 && u + v <= 1.0) {
         state.Hits = true;
         state.IntersectionPoint = vector.ScaleFromOrigin(t);
         state.Drawable = drawable;
         state.T = t;
      }
      else {
         state.Hits = false;
      }
      return state;
   }

   public static Vector GetNormal(Triangle triangle, IntersectionState state) {
      return new Vector(triangle._vertex0, triangle._normalDirection);
   }

   @Override
   public double BRDF(IntersectionState state, Vector cameraRay, Vector lightRay) {
      return 0;
   }

   @Override
   public double GetVolume() {
      return 0;
   }

   @Override
   public BoundingBox GetBoundingBox() {
      return null;
   }

   @Override
   public Point getLocation() {
      return null;
   }

   @Override
   public double getLumens() {
      return 0;
   }
}
